package com.springboot.spring03tx.service.impl;

import com.springboot.spring03tx.bean.Book;
import com.springboot.spring03tx.dao.AccountDao;
import com.springboot.spring03tx.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springboot.spring03tx.service.UserService;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
/*
场景：用户结账，炸了以后，金额扣减回滚，库存不回滚。
        * 注意：【一定关注异常的传播链】
        * 实现：
        *    checkout(){
     *        //自己的操作；
     *        扣减金额： //REQUIRED
     *        扣减库存： //REQUIRES_NEW
     *    }
*/

/*
复杂案例
A {
     *      B(){  //REQUIRED
     *          F();//REQUIRES_NEW
     *          G();//REQUIRED
     *          H();//REQUIRES_NEW
     *      }
     *      C(){  //REQUIRES_NEW
     *         I();//REQUIRES_NEW
     *         J();//REQUIRED
     *      }
     *      D(){   //REQUIRES_NEW
     *          K();//REQUIRES_NEW
     *          L();//REQUIRES_NEW //点位2： 10/0； K,F,H,C(i,j) = ok, E整个代码走不到，剩下炸
     *      }
     *      E(){   //REQUIRED
     *          M();//REQUIRED
     *          //点位3：10/0；  F,H,C(i,j),D(K,L)= ok
     *          N();//REQUIRES_NEW
     *      }
     *
     *      int i = 10/0;  //此时A炸，点位1：C（I，J）,D(K，L) ，F，H,N 不炸
     *  }
*/


/*
传播行为：参数设置项也会传播：如果小事务和大事务公用一个事务，小事务要按照大事务的设置，小事务自己的设置失效
eg：执行
*/
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    BookDao bookDao;
    @Autowired
    AccountDao accountDao;
    @Override
    @Transactional(timeout = 0)
    /*
传播行为：参数设置项也会传播：如果小事务和大事务公用一个事务，小事务要按照大事务的设置，小事务自己的设置失效
eg：执行checkout时，以大事务checkout设置的timeout=0为准，下面查询图书信息设置的小事务设置（eg：timeout = 3）失效
*/
    public void checkout(String username, Integer bookId, Integer buyNum) throws InterruptedException {
        //1、查询图书信息
        Book book = bookDao.getBookById(bookId);
        BigDecimal price = book.getPrice();
        //2、计算扣减额度
        BigDecimal total = new BigDecimal(buyNum).multiply(price);
        //模拟超时
        //Thread.sleep(0);
        //3、扣减余额  //REQUIRED
        accountDao.updateBalanceByUsername(username,total);
        //4、扣减库存 //REQUIRES_NEW
        bookDao.updataBookStock(bookId,buyNum);

    }
}
